package com.gp.service.calculate;

import java.util.Date;
import java.util.List;

import com.gp.model.entity.BaseOrder;
import com.gp.service.calculate.Result.IncomeDetail;

/**
 * @date: 2017年11月28日
 * @author: 弓成龙
 * @email: gcx909109@sina.cn
 * @description: 利润计算处理器
 * 
 *               利润计算方式： 从订单总额中抽取相应的比例
 *               <ul>
 *               <li>一级分销商利润构成：<br>
 *               1. 直属二级分销商订单总额的相应比例(按照计算规则提供的抽取比例，初步设定为5%)<br>
 *               2. 直属三级分销商订单总额的相应比例(按照计算规则提供的抽取比例，初步设定为8%)<br>
 *               3. 直属订单总额的相应比例(按照计算规则提供的抽取比例，初步设定为12%)</li>
 *               <li>二级分销商利润构成：<br>
 *               1. 直属三级分销商订单总额的相应比例(按照计算规则提供的抽取比例，初步设定为8%)<br>
 *               2. 直属订单总额的相应比例(按照计算规则提 供的抽取比例，初步设定为12%)</li>
 *               <li>三级分销商利润构成： <br>
 *               1. 直属订单总额的相应比例(按照计算规则提供的抽取比例，初步设定为12%)</li>
 *               </ul>
 **/
public class ProfitCalculateProcessor extends CalculateProcessor {

  // 定义返回结果
  private Result result = new Result();

  // 私有构造方法，防止创建多个实例
  private ProfitCalculateProcessor() {}

  /**
   * 通过此方法获取ProfitCalculateProcessor对象
   * 
   * @return ProfitCalculateProcessor对象
   */
  public static ProfitCalculateProcessor getInStance() {
    return SingleProfitCalculateHolder.profitCalculateProcessor;
  }

  @Override
  public void calculate() {
    ProfitDataInfo data = (ProfitDataInfo) getCalculateData();
    ProfitRuleInfo rule = (ProfitRuleInfo) getCalculateRule();
    result.setSecondLevelIncome(calculateSecondLevel(data.getOrderBySecondLevel(), rule.getSecondProfitRate()));
    result.setThirdLevelIncome(calculateThirdLevel(data.getOrderByThirdLevel(), rule.getThirdProfitRate()));
    result.setDirectIncome(calculateDirectLevel(data.getOrderByself(), rule.getDirectProfitRate()));
    result.setGeneralIncome(calculateAllMoney());
    result.setCreateTime(new Date().toString());
  }

  /**
   * 计算由二级分销商创造的收入
   * 
   * @param order 二级分销商的订单
   * @param rule 二级分销商的计算规则
   * @return 总收入
   */
  private Integer calculateSecondLevel(List<BaseOrder> orderList, Double rate) {
    int allMoney = 0;
    for (BaseOrder order : orderList) {
      allMoney = allMoney + Integer.valueOf(order.getTotalPrice());
      IncomeDetail income = result.createIncomeDetail(order.getUsername(), order.getOrderValiddate(),
          order.getOrderCode(), Integer.valueOf(order.getTotalPrice()));
      result.getSecondLevelIncomeDetail().add(income);
    }
    return (int) (allMoney * rate);
  }

  /**
   * 计算由三级分销商创造的收入
   * 
   * @param order 三级分销商的订单
   * @param rule 三级分销商的计算规则
   * @return 总收入
   */
  private Integer calculateThirdLevel(List<BaseOrder> orderList, Double rate) {
    int allMoney = 0;
    for (BaseOrder order : orderList) {
      allMoney = allMoney + Integer.valueOf(order.getTotalPrice());
      IncomeDetail income = result.createIncomeDetail(order.getUsername(), order.getOrderValiddate(),
          order.getOrderCode(), Integer.valueOf(order.getTotalPrice()));
      result.getThirdLevelIncomeDetail().add(income);
    }
    return (int) (allMoney * rate);
  }

  /**
   * 计算直属的收入
   * 
   * @param order 自己创造的订单
   * @param rule 计算规则
   * @return 总收入
   */
  private Integer calculateDirectLevel(List<BaseOrder> orderList, Double rate) {
    int allMoney = 0;
    for (BaseOrder order : orderList) {
      allMoney = allMoney + Integer.valueOf(order.getTotalPrice());
      IncomeDetail income = result.createIncomeDetail(order.getUsername(), order.getOrderValiddate(),
          order.getOrderCode(),Integer.valueOf(order.getTotalPrice()));
      result.getDirectIncomeDetail().add(income);
    }
    return (int) (allMoney * rate);
  }
  
  /**
   * 计算总收入
   * @return 总收入
   */
  private Integer calculateAllMoney() {
    return result.getDirectIncome() + result.getSecondLevelIncome() + result.getThirdLevelIncome();
  }
  
  /**
   * 调用此方法得到计算的结果，必须要执行首先执行calculate()
   * 
   * @return Result 封装执行结果的对象
   */
  public Result getResult() {
    return this.result;
  }

  private static class SingleProfitCalculateHolder {
    public static ProfitCalculateProcessor profitCalculateProcessor = new ProfitCalculateProcessor();
  }
}
